package cn.net.xyan.easy.gwt.client;

import cn.net.xyan.easy.gwt.shared.StringUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.rpc.RpcRequestBuilder;
import org.fusesource.restygwt.client.Defaults;
import org.fusesource.restygwt.client.RestService;
import org.gwtbootstrap3.extras.bootbox.client.Bootbox;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zarra on 16/2/16.
 */
public class EZGwt {

    static ObjectFactory factory;


    static private ObjectFactory factory() {
        if (factory == null) {
            Defaults.setServiceRoot(EZGwt.appFullRoot());
            factory = GWT.create(ObjectFactory.class);
        }
        return factory;
    }

    static public <T, V> T create(Class<V> clazz) {
        T t = factory().newInstance(clazz);
        if (t instanceof RestService){
           // Defaults.setServiceRoot(appRoot());
            //Resource resource = new Resource( appRoot());
            //((RestServiceProxy)t).setResource(resource);
        }
        return t;
    }

    static public RpcRequestBuilder createRpcRequestBuilder() {
        EZRpcRequestBuilder rpcRequestBuilder = new EZRpcRequestBuilder();

        rpcRequestBuilder.setHeader("X-CSRF-TOKEN", CSRFToken());

        return rpcRequestBuilder;
    }

    static public Element addElementToHead(String tag, Map<String, String> attributes, String text) {
        Element element = DOM.createElement(tag);

        for (Map.Entry<String, String> entry : attributes.entrySet()) {
            element.setAttribute(entry.getKey(), entry.getValue());
        }

        if (!StringUtils.isEmpty(text)) {
            element.setInnerSafeHtml(SafeHtmlUtils.fromString(text));
        }

        Document.get().getHead().appendChild(element);

        return element;
    }

    static public void loadExternalJavaScript(String path, String file) {
        Map<String, String> attributes = new HashMap<>();
        attributes.put("src", path + file);
        attributes.put("type", "text/javascript");
        addElementToHead("script", attributes, null);
    }

    static public native String getEnvValue(String key)/*-{
        return $wnd.ENV[key];
    }-*/;

    static public String appRoot() {
        return getEnvValue("APP_ROOT");
    }

    static public String appFullRoot() {
        return getEnvValue("APP_FULL");
    }

    static public String CSRFToken() {
        return getEnvValue("CSRF_Token");
    }

    static public String CSRFKey() {
        return getEnvValue("CSRF_ParameterName");
    }

    public static native String format(String str, Object... arr)/*-{
        var i = -1;

        function callback(exp, p0, p1, p2, p3, p4) {
            if (exp == '%%') return '%';
            if (arr[++i] === undefined) return undefined;
            var exp = p2 ? parseInt(p2.substr(1)) : undefined;
            var base = p3 ? parseInt(p3.substr(1)) : undefined;
            var val;
            switch (p4) {
                case 's':
                    val = arr[i];
                    break;
                case 'c':
                    val = arr[i][0];
                    break;
                case 'f':
                    val = parseFloat(arr[i]).toFixed(exp);
                    break;
                case 'p':
                    val = parseFloat(arr[i]).toPrecision(exp);
                    break;
                case 'e':
                    val = parseFloat(arr[i]).toExponential(exp);
                    break;
                case 'x':
                    val = parseInt(arr[i]).toString(base ? base : 16);
                    break;
                case 'd':
                    val = parseFloat(parseInt(arr[i], base ? base : 10).toPrecision(exp)).toFixed(0);
                    break;
            }
            val = typeof(val) == 'object' ? JSON.stringify(val) : val.toString(base);
            var sz = parseInt(p1); // padding size
            var ch = p1 && p1[0] == '0' ? '0' : ' ';
            while (val.length < sz) val = p0 !== undefined ? val + ch : ch + val;
            return val;
        }

        var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd])/g;
        return str.replace(regex, callback);
    }-*/;

    static public void logout(RequestCallback requestCallback) {
        try {
            RequestBuilder rb = new RequestBuilder(
                    RequestBuilder.POST,
                    StringUtils.format("{0}{1}", appRoot(), "/logout"));
            rb.setHeader("X-CSRF-TOKEN", CSRFToken());

            rb.setCallback(requestCallback);
            rb.send();
        } catch (RequestException e) {
            Bootbox.alert(e.getMessage());
            //e.printStackTrace();
        }

    }
}
